<?php
/**
 * This file defines the {@see \BF\Drawing\ColorTool} class.
 *
 * @author     Kado <ulfikado@gmail.com>
 * @category   Beluga PHP5.3+ Framework
 * @package    BF\Drawing
 * @since      2015-01-31 00:29
 * @subpackage Core
 * @version    0.1
 */

namespace BF\Drawing
{

   /**
    * A static color helping class
    *
    * @since      v0.1
    */
   class ColorTool
   {

      # <editor-fold defaultstate="collapsed" desc=" - - -   P R I V A T E   S T A T I C   F I E L D S   - - - - - - - - - - - - - - -">

      # <editor-fold defaultstate="collapsed" desc="Color name => RGB Associations">

      private static $ColornameRGB = array(
         'aliceblue'            => array( 240, 248, 255 ), 'antiquewhite'         => array( 250, 235, 215 ),
         'aqua'                 => array( 0, 255, 255 ),   'aquamarine'           => array( 127, 255, 212 ),
         'azure'                => array( 240, 255, 255 ), 'beige'                => array( 245, 245, 220 ),
         'bisque'               => array( 255, 228, 196 ), 'black'                => array( 0, 0, 0 ),
         'blanchedalmond'       => array( 255, 235, 205 ), 'blue'                 => array( 0, 0, 255 ),
         'blueviolet'           => array( 138, 43, 226 ),  'brown'                => array( 165, 42, 42 ),
         'burlywood'            => array( 222, 184, 135 ), 'cadetblue'            => array( 95, 158, 160 ),
         'chartreuse'           => array( 127, 255, 0 ),   'chocolate'            => array( 210, 105, 30 ),
         'coral'                => array( 255, 127, 80 ),  'cornflowerblue'       => array( 100, 149, 237 ),
         'cornsilk'             => array( 255, 248, 220 ), 'crimson'              => array( 220, 20, 60 ),
         'cyan'                 => array( 0, 255, 255 ),   'darkblue'             => array( 0, 0, 139 ),
         'darkcyan'             => array( 0, 139, 139 ),   'darkgoldenrod'        => array( 184, 134, 11 ),
         'darkgray'             => array( 169, 169, 169 ), 'darkgreen'            => array( 0, 100, 0 ),
         'darkkhaki'            => array( 189, 183, 107 ), 'darkmagenta'          => array( 139, 0, 139 ),
         'darkolivegreen'       => array( 85, 107, 47 ),   'darkorange'           => array( 255, 140, 0 ),
         'darkorchid'           => array( 153, 50, 204 ),  'darkred'              => array( 139, 0, 0 ),
         'darksalmon'           => array( 233, 150, 122 ), 'darkseagreen'         => array( 143, 188, 143 ),
         'darkslateblue'        => array( 72, 61, 139 ),   'darkslategray'        => array( 47, 79, 79 ),
         'darkturquoise'        => array( 0, 206, 209 ),   'darkviolet'           => array( 148, 0, 211 ),
         'deeppink'             => array( 255, 20, 147 ),  'deepskyblue'          => array( 0, 191, 255 ),
         'dimgray'              => array( 105, 105, 105 ), 'dodgerblue'           => array( 30, 144, 255 ),
         'firebrick'            => array( 178, 34, 34 ),   'floralwhite'          => array( 255, 250, 240 ),
         'forestgreen'          => array( 34, 139, 34 ),   'fuchsia'              => array( 255, 0, 255 ),
         'gainsboro'            => array( 220, 220, 220 ), 'ghostwhite'           => array( 248, 248, 255 ),
         'gold'                 => array( 255, 215, 0 ),   'goldenrod'            => array( 218, 165, 32 ),
         'gray'                 => array( 128, 128, 128 ), 'green'                => array( 0, 128, 0 ),
         'greenyellow'          => array( 173, 255, 47 ),  'honeydew'             => array( 240, 255, 240 ),
         'hotpink'              => array( 255, 105, 180 ), 'indianred'            => array( 205, 92, 92 ),
         'indigo'               => array( 75, 0, 130 ),    'ivory'                => array( 255, 255, 240 ),
         'khaki'                => array( 240, 230, 140 ), 'lavender'             => array( 230, 230, 250 ),
         'lavenderblush'        => array( 255, 240, 245 ), 'lawngreen'            => array( 124, 252, 0 ),
         'lemonchiffon'         => array( 255, 250, 205 ), 'lightblue'            => array( 173, 216, 230 ),
         'lightcoral'           => array( 240, 128, 128 ), 'lightcyan'            => array( 224, 255, 255 ),
         'lightgoldenrodyellow' => array( 250, 250, 210 ), 'lightgrey'            => array( 211, 211, 211 ),
         'lightgreen'           => array( 144, 238, 144 ), 'lightpink'            => array( 255, 182, 193 ),
         'lightsalmon'          => array( 255, 160, 122 ), 'lightseagreen'        => array( 32, 178, 170 ),
         'lightskyblue'         => array( 135, 206, 250 ), 'lightslategray'       => array( 119, 136, 153 ),
         'lightsteelblue'       => array( 176, 196, 222 ), 'lightyellow'          => array( 255, 255, 224 ),
         'lime'                 => array( 0, 255, 0 ),     'limegreen'            => array( 50, 205, 50 ),
         'linen'                => array( 250, 240, 230 ), 'magenta'              => array( 255, 0, 255 ),
         'maroon'               => array( 128, 0, 0 ),     'mediumaquamarine'     => array( 102, 205, 170 ),
         'mediumblue'           => array( 0, 0, 205 ),     'mediumorchid'         => array( 186, 85, 211 ),
         'mediumpurple'         => array( 147, 112, 216 ), 'mediumseagreen'       => array( 60, 179, 113 ),
         'mediumslateblue'      => array( 123, 104, 238 ), 'mediumspringgreen'    => array( 0, 250, 154 ),
         'mediumturquoise'      => array( 72, 209, 204 ),  'mediumvioletred'      => array( 199, 21, 133 ),
         'midnightblue'         => array( 25, 25, 112 ),   'mintcream'            => array( 245, 255, 250 ),
         'mistyrose'            => array( 255, 228, 225 ), 'moccasin'             => array( 255, 228, 181 ),
         'navajowhite'          => array( 255, 222, 173 ), 'navy'                 => array( 0, 0, 128 ),
         'oldlace'              => array( 253, 245, 230 ), 'olive'                => array( 128, 128, 0 ),
         'olivedrab'            => array( 107, 142, 35 ),  'orange'               => array( 255, 165, 0 ),
         'orangered'            => array( 255, 69, 0 ),    'orchid'               => array( 218, 112, 214 ),
         'palegoldenrod'        => array( 238, 232, 170 ), 'palegreen'            => array( 152, 251, 152 ),
         'paleturquoise'        => array( 175, 238, 238 ), 'palevioletred'        => array( 216, 112, 147 ),
         'papayawhip'           => array( 255, 239, 213 ), 'peachpuff'            => array( 255, 218, 185 ),
         'peru'                 => array( 205, 133, 63 ),  'pink'                 => array( 255, 192, 203 ),
         'plum'                 => array( 221, 160, 221 ), 'powderblue'           => array( 176, 224, 230 ),
         'purple'               => array( 128, 0, 128 ),   'red'                  => array( 255, 0, 0 ),
         'rosybrown'            => array( 188, 143, 143 ), 'royalblue'            => array( 65, 105, 225 ),
         'saddlebrown'          => array( 139, 69, 19 ),   'salmon'               => array( 250, 128, 114 ),
         'sandybrown'           => array( 244, 164, 96 ),  'seagreen'             => array( 46, 139, 87 ),
         'seashell'             => array( 255, 245, 238 ), 'sienna'               => array( 160, 82, 45 ),
         'silver'               => array( 192, 192, 192 ), 'skyblue'              => array( 135, 206, 235 ),
         'slateblue'            => array( 106, 90, 205 ),  'slategray'            => array( 112, 128, 144 ),
         'snow'                 => array( 255, 250, 250 ), 'springgreen'          => array( 0, 255, 127 ),
         'steelblue'            => array( 70, 130, 180 ),  'tan'                  => array( 210, 180, 140 ),
         'teal'                 => array( 0, 128, 128 ),   'thistle'              => array( 216, 191, 216 ),
         'tomato'               => array( 255, 99, 71 ),   'turquoise'            => array( 64, 224, 208 ),
         'violet'               => array( 238, 130, 238 ), 'wheat'                => array( 245, 222, 179 ),
         'white'                => array( 255, 255, 255 ), 'whitesmoke'           => array( 245, 245, 245 ),
         'yellow'               => array( 255, 255, 0 ),   'yellowgreen'          => array( 154, 205, 50 )
      );

      # </editor-fold>

      # <editor-fold defaultstate="collapsed" desc="Color name => HEX Associations">

      private static $ColornameHex = array(
         'aliceblue'            => '#F0F8FF', 'antiquewhite'         => '#FAEBD7', 'aqua'                 => '#00FFFF',
         'aquamarine'           => '#7FFFD4', 'azure'                => '#F0FFFF', 'beige'                => '#F5F5DC',
         'bisque'               => '#FFE4C4', 'black'                => '#000000', 'blanchedalmond'       => '#FFEBCD',
         'blue'                 => '#0000FF', 'blueviolet'           => '#8A2BE2', 'brown'                => '#A52A2A',
         'burlywood'            => '#DEB887', 'cadetblue'            => '#5F9EA0', 'chartreuse'           => '#7FFF00',
         'chocolate'            => '#D2691E', 'coral'                => '#FF7F50', 'cornflowerblue'       => '#6495ED',
         'cornsilk'             => '#FFF8DC', 'crimson'              => '#DC143C', 'cyan'                 => '#00FFFF',
         'darkblue'             => '#00008B', 'darkcyan'             => '#008B8B', 'darkgoldenrod'        => '#B8860B',
         'darkgray'             => '#A9A9A9', 'darkgreen'            => '#006400', 'darkkhaki'            => '#BDB76B',
         'darkmagenta'          => '#8B008B', 'darkolivegreen'       => '#556B2F', 'darkorange'           => '#FF8C00',
         'darkorchid'           => '#9932CC', 'darkred'              => '#8B0000', 'darksalmon'           => '#E9967A',
         'darkseagreen'         => '#8FBC8F', 'darkslateblue'        => '#483D8B', 'darkslategray'        => '#2F4F4F',
         'darkturquoise'        => '#00CED1', 'darkviolet'           => '#9400D3', 'deeppink'             => '#FF1493',
         'deepskyblue'          => '#00BFFF', 'dimgray'              => '#696969', 'dodgerblue'           => '#1E90FF',
         'firebrick'            => '#B22222', 'floralwhite'          => '#FFFAF0', 'forestgreen'          => '#228B22',
         'fuchsia'              => '#FF00FF', 'gainsboro'            => '#DCDCDC', 'ghostwhite'           => '#F8F8FF',
         'gold'                 => '#FFD700', 'goldenrod'            => '#DAA520', 'gray'                 => '#808080',
         'green'                => '#008000', 'greenyellow'          => '#ADFF2F', 'honeydew'             => '#F0FFF0',
         'hotpink'              => '#FF69B4', 'indianred'            => '#CD5C5C', 'indigo'               => '#4B0082',
         'ivory'                => '#FFFFF0', 'khaki'                => '#F0E68C', 'lavender'             => '#E6E6FA',
         'lavenderblush'        => '#FFF0F5', 'lawngreen'            => '#7CFC00', 'lemonchiffon'         => '#FFFACD',
         'lightblue'            => '#ADD8E6', 'lightcoral'           => '#F08080', 'lightcyan'            => '#E0FFFF',
         'lightgoldenrodyellow' => '#FAFAD2', 'lightgrey'            => '#D3D3D3', 'lightgreen'           => '#90EE90',
         'lightpink'            => '#FFB6C1', 'lightsalmon'          => '#FFA07A', 'lightseagreen'        => '#20B2AA',
         'lightskyblue'         => '#87CEFA', 'lightslategray'       => '#778899', 'lightsteelblue'       => '#B0C4DE',
         'lightyellow'          => '#FFFFE0', 'lime'                 => '#00FF00', 'limegreen'            => '#32CD32',
         'linen'                => '#FAF0E6', 'magenta'              => '#FF00FF', 'maroon'               => '#800000',
         'mediumaquamarine'     => '#66CDAA', 'mediumblue'           => '#0000CD', 'mediumorchid'         => '#BA55D3',
         'mediumpurple'         => '#9370D8', 'mediumseagreen'       => '#3CB371', 'mediumslateblue'      => '#7B68EE',
         'mediumspringgreen'    => '#00FA9A', 'mediumturquoise'      => '#48D1CC', 'mediumvioletred'      => '#C71585',
         'midnightblue'         => '#191970', 'mintcream'            => '#F5FFFA', 'mistyrose'            => '#FFE4E1',
         'moccasin'             => '#FFE4B5', 'navajowhite'          => '#FFDEAD', 'navy'                 => '#000080',
         'oldlace'              => '#FDF5E6', 'olive'                => '#808000', 'olivedrab'            => '#6B8E23',
         'orange'               => '#FFA500', 'orangered'            => '#FF4500', 'orchid'               => '#DA70D6',
         'palegoldenrod'        => '#EEE8AA', 'palegreen'            => '#98FB98', 'paleturquoise'        => '#AFEEEE',
         'palevioletred'        => '#D87093', 'papayawhip'           => '#FFEFD5', 'peachpuff'            => '#FFDAB9',
         'peru'                 => '#CD853F', 'pink'                 => '#FFC0CB', 'plum'                 => '#DDA0DD',
         'powderblue'           => '#B0E0E6', 'purple'               => '#800080', 'red'                  => '#FF0000',
         'rosybrown'            => '#BC8F8F', 'royalblue'            => '#4169E1', 'saddlebrown'          => '#8B4513',
         'salmon'               => '#FA8072', 'sandybrown'           => '#F4A460', 'seagreen'             => '#2E8B57',
         'seashell'             => '#FFF5EE', 'sienna'               => '#A0522D', 'silver'               => '#C0C0C0',
         'skyblue'              => '#87CEEB', 'slateblue'            => '#6A5ACD', 'slategray'            => '#708090',
         'snow'                 => '#FFFAFA', 'springgreen'          => '#00FF7F', 'steelblue'            => '#4682B4',
         'tan'                  => '#D2B48C', 'teal'                 => '#008080', 'thistle'              => '#D8BFD8',
         'tomato'               => '#FF6347', 'turquoise'            => '#40E0D0', 'violet'               => '#EE82EE',
         'wheat'                => '#F5DEB3', 'white'                => '#FFFFFF', 'whitesmoke'           => '#F5F5F5',
         'yellow'               => '#FFFF00', 'yellowgreen'          => '#9ACD32'
      );

      # </editor-fold>

      # </editor-fold>

      # <editor-fold defaultstate="collapsed" desc=" - - >   P R I V A T E   C O N S T R U C T O R   - - - - - - - - - - - - - - - - -">

      private function __construct() {  }

      # </editor-fold>

      # <editor-fold defaultstate="collapsed" desc=" - - -   P U B L I C   S T A T I C   M E T H O D S   - - - - - - - - - - - - - - -">

      /**
       * Returns if the defined color string is a usable hexadecimal color definition.
       *
       * @param  mixed $colorDefinition
       * @return boolean
       */
      public static function IsHexFormat( $colorDefinition )
      {

         if ( \is_array( $colorDefinition ) )
         {
            return false;
         }

         return (bool) \preg_match(
            '~^#?([a-f0-9]{2}|[a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{8})$~i',
            $colorDefinition
         );

      }

      /**
       * Converts the defined color into a RGB color definition (a numeric indicated array 0=R 1=G 2=B
       *
       * @param  string $colorDefinition Color name or hexadecimal color definition
       * @return array Or boolean FALSE
       */
      public static function Color2Rgb( $colorDefinition )
      {
         if ( \is_array( $colorDefinition ) )
         {
            if ( \count( $colorDefinition ) > 2 && \count( $colorDefinition ) < 5 )
            {
               return $colorDefinition;
            }
            throw new \BF\ArgumentFormatException(
               'colorDefinition',
               $colorDefinition,
               'A (a)rgb(a) array with 3-4 Elements is required!'
            );
         }
         if ( self::IsHexFormat( $colorDefinition ) )
         {
            return self::Hex2Rgb( $colorDefinition );
         }
         $uc = \strtolower( $colorDefinition );
         if ( isset( self::$ColornameRGB[ $uc ] ) )
         {
            return self::$ColornameRGB[$uc];
         }
         if ( false !== ( $hex = self::Rgb2Hex( $colorDefinition ) ) )
         {
            return self::Hex2Rgb( $hex );
         }
         return false;
      }

      /**
       * Converts the defined Color definition into hexadecimal representation.
       *
       * @param  string|array $colorDefinition Color name, RGB color array or Hex color definition
       * @return string|FALSE
       */
      public static function Color2Hex( $colorDefinition )
      {
         if ( \is_array( $colorDefinition ) )
         {
            if ( \count( $colorDefinition ) != 3 )
            {
               throw new \BF\ArgumentFormatException(
                  'colorDefinition',
                  $colorDefinition,
                  'A rgb array with 3 Elements is required!'
               );
            }
            return self::Rgb2Hex( $colorDefinition );
         }
         if ( self::IsHexFormat( $colorDefinition ) )
         {
            return $colorDefinition;
         }
         $uc = \strtolower( $colorDefinition );
         if ( isset( self::$ColornameHex[ $uc ] ) )
         {
            return \strtolower( self::$ColornameHex[ $uc ] );
         }
         if ( false !== ( $hex = self::Rgb2Hex( $colorDefinition ) ) )
         {
            return $hex;
         }
         return false;
      }

      public static function Hex2Rgb( $color )
      {
         if ( $color[ 0 ] == '#' )
         {
            $color = \substr( $color, 1 );
         }
         if ( \strlen( $color ) == 8 )
         {
            $color = \substr( $color, 2 );
         }
         if ( \strlen( $color ) == 6 )
         {
            $r = $color[ 0 ] . $color[ 1 ];
            $g = $color[ 2 ] . $color[ 3 ];
            $b = $color[ 4 ] . $color[ 5 ];
         }
         elseif ( \strlen( $color ) == 3 )
         {
            $r = $color[ 0 ] . $color[ 0 ];
            $g = $color[ 1 ] . $color[ 1 ];
            $b = $color[ 2 ] . $color[ 2 ];
         }
         elseif ( \strlen( $color ) == 2 )
         {
            $r = $color;
            $g = $color;
            $b = $color;
         }
         else
         {
            return false;
         }
         return array( \hexdec( $r ), \hexdec( $g ), \hexdec( $b ) );
      }

      /**
       * Converts a RGB array or the 3 r, g, b values into a hexadecimal color representation.
       *
       * @param  array|integer $r RGB Array or the red bit value.
       * @param  integer       $g The green bit value.
       * @param  integer       $b The blue bit value
       * @return boolean
       */
      public static function Rgb2Hex( $r, $g = -1, $b = -1 )
      {
         $m = null;
         if ( \is_array( $r ) )
         {
            if ( \count( $r ) != 3 )
            {
               return false;
            }
            \array_change_key_case( $r, \CASE_LOWER );
            if ( isset( $r[ 'r' ] ) && isset( $r[ 'g' ] ) && isset( $r[ 'b' ] ) )
            {
               $g = $r[ 'g' ];
               $b = $r[ 'b' ];
               $r = $r[ 'r' ];
            }
            elseif ( isset( $r[ 'red' ] ) && isset( $r[ 'green' ] ) && isset( $r[ 'blue' ] ) )
            {
               $g = $r[ 'green' ];
               $b = $r[ 'blue' ];
               $r = $r[ 'red' ];
            }
            else
            {
               $rgb = $r;
               list( $r, $g, $b ) = $rgb;
            }

         }
         elseif ( \preg_match( '~^(rgb\s*\()?(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)?$~', $r, $m ) )
         {
            list( $ignore, $r, $g, $b ) = $m;
            $ignore = null;
         }
         elseif ( ! \is_int( $r ) )
         {
            return false;
         }
         $r1 = \intval( $r );
         $g1 = \intval( $g );
         $b1 = \intval( $b );
         $r = \dechex( $r1 < 0 ? 0 : ( $r1 > 255 ? 255 : $r1 ) );
         $g = \dechex( $g1 < 0 ? 0 : ( $g1 > 255 ? 255 : $g1 ) );
         $b = \dechex( $b1 < 0 ? 0 : ( $b1 > 255 ? 255 : $b1 ) );
         return \sprintf( '#%02s%02s%02s', $r, $g, $b );
      }

      /**
       * Returns, if the defined color is associated to a known netscape color name. If so the method returns true, and
       * the parameter $colornameResult returns the associated color name.
       *
       * @param string|array $colorDefinition
       * @param string       $colornameResult
       */
      public static function IsNamedColor( $colorDefinition, &$colornameResult )
      {
         if ( false === ( $hex = self::Color2Hex( $colorDefinition ) ) )
         {
            return false;
         }
         if ( false !== ( $colorName = \array_search( \strtoupper( $hex ), self::$ColornameHex ) ) )
         {
            $colornameResult = $colorName;
            return true;
         }
         return false;
      }

      public static function GetColorNames()
      {
         return \array_keys( self::$ColornameHex );
      }

      # </editor-fold>

   }

}

